//
//  UIImage+Data.m
//  ZYWebImage
//
//  Created by wangzhipan on 2025/3/18.
//

#import "UIImage+Data.h"
#import "UIImage+MetaData.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "demux.h"
#import "mux.h"
#import "sharpyuv.h"
#import "decode.h"
#import "encode.h"
#import "types.h"
#import "mux_types.h"
#import "format_constants.h"

@implementation UIImage (Data)
- (NSData *)zy_dataOfFormat:(ZYImageFormat)format
{
    NSData *data = self.zy_metaData;
    /*
     先拿下载好的原始data，有的话直接返回
     */
    if (data) {
        return data;
    }
    
    switch (format) {
        case ZYImageFormatPng:
            data = [self pngImageData];
            break;
        case ZYImageFormatGif:
            data = [self gifImageData];
            break;
        case ZYImageFormatJpeg:
            data = [self jpegImageData];
            break;
        case ZYImageFormatWebp:
            data = [self webPImageData];
            break;
            
        default:
            data = [self pngImageData];;
    }
    return data;
}

- (NSData *)pngImageData
{
    return UIImagePNGRepresentation(self);
}

- (NSData *)jpegImageData
{
    return UIImageJPEGRepresentation(self, 1);
}

/**
 * 将 GIF 格式的 UIImage 转换为 NSData
 * @param gifImage GIF 格式的 UIImage 对象
 * @return 返回 GIF 格式的 NSData 数据
 */
- (NSData *)gifImageData
{
    // 1. 检查是否是动图
    if (!self.images || self.images.count <= 1) {
        // 不是动图，使用普通方式转换
        return [self pngImageData];
    }
    
    // 2. 创建 GIF 数据
    NSMutableData *gifData = [NSMutableData data];
    
    // 3. 获取 GIF 类型标识符，兼容新旧 API
     CFStringRef gifUTI;
     
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
    if (@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)) {
        // 使用新的 UTType API
        CFStringRef tempUTI = UTTypeCopyPreferredTagWithClass(
            (__bridge CFStringRef)@"com.compuserve.gif",
            kUTTagClassFilenameExtension);
        
        // 检查返回值是否为 NULL
        if (tempUTI != NULL) {
            gifUTI = tempUTI;
        }
    } else {
        gifUTI = kUTTypeGIF;
    }
#else
    gifUTI = kUTTypeGIF;
#endif
     
     // 如果上述方法都失败，使用硬编码的字符串
     if (!gifUTI) {
         gifUTI = CFSTR("com.compuserve.gif");
     }
    
    // 3. 创建 CGImageDestination 用于生成 GIF 数据
    CGImageDestinationRef destination = CGImageDestinationCreateWithData(
                                                                         (__bridge CFMutableDataRef)gifData,
                                                                         gifUTI,
                                                                         self.images.count,
                                                                         NULL
                                                                         );
    
    if (!destination) {
        return nil;
    }
    
    // 5. 设置 GIF 属性
    NSDictionary *gifProperties = @{
        (__bridge NSString *)kCGImagePropertyGIFDictionary: @{
            (__bridge NSString *)kCGImagePropertyGIFHasGlobalColorMap: @YES,
            (__bridge NSString *)kCGImagePropertyColorModel: (__bridge NSString *)kCGImagePropertyColorModelRGB,
            (__bridge NSString *)kCGImagePropertyDepth: @8,
            (__bridge NSString *)kCGImagePropertyGIFLoopCount: @0  // 0 表示无限循环
        }
    };
    
    CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)gifProperties);
    
    // 6. 计算每一帧的持续时间
    float frameDuration = self.duration / self.images.count;
    
    // 7. 添加每一帧到 GIF
    for (NSUInteger i = 0; i < self.images.count; i++) {
        UIImage *frameImage = [self.images objectAtIndex:i];
        
        // 设置每一帧的属性
        NSDictionary *frameProperties = @{
            (__bridge NSString *)kCGImagePropertyGIFDictionary: @{
                (__bridge NSString *)kCGImagePropertyGIFDelayTime: @(frameDuration)
            }
        };
        
        // 添加帧到目标 GIF
        CGImageDestinationAddImage(destination, frameImage.CGImage, (__bridge CFDictionaryRef)frameProperties);
    }
    
    // 8. 完成 GIF 创建
    if (!CGImageDestinationFinalize(destination)) {
        CFRelease(destination);
        return nil;
    }
    CFRelease(destination);
    return gifData;
}

/**
 * 将 WebP 格式的 UIImage 转换为 NSData
 * @param image WebP 格式的 UIImage 对象
 * @return 返回 WebP 格式的 NSData 数据
 */
- (NSData *)webPImageData
{
    
    // 1. 使用 WebP 编码器
    // 创建编码配置
    WebPConfig config;
    if (!WebPConfigInit(&config)) {
        return nil;
    }
    
    // 设置编码质量和参数
    config.quality = 75.0f; // 0-100
    config.lossless = 0;    // 有损压缩
    config.method = 4;      // 压缩速度和质量的平衡，范围0-6
    
    // 3. 将 UIImage 转换为 RGBA 数据
    CGImageRef imageRef = self.CGImage;
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    size_t bitsPerComponent = 8;
    size_t bytesPerRow = width * 4;
    
    uint8_t *rgba = malloc(width * height * 4);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgba,
                                               width,
                                               height,
                                               bitsPerComponent,
                                               bytesPerRow,
                                               colorSpace,
                                               kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);
    
    // 4. 编码为 WebP
    uint8_t *output;
    size_t outputSize;
    
    outputSize = WebPEncodeRGBA(rgba,
                               (int)width,
                               (int)height,
                               (int)bytesPerRow,
                               config.quality,
                               &output);
    
    free(rgba);
    
    if (outputSize == 0) {
        return nil;
    }
    
    // 5. 创建 NSData
    NSData *webpData = [NSData dataWithBytes:output length:outputSize];
    WebPFree(output);
    return webpData;
}
@end
